package com.apptonelabs.pnrenquiry;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class PNRStatusCrawller {
	public static void main(String args[]) {
		try {
			String pnr1 = "6538118294";
			String reqStr = "lccp_pnrno1=" + pnr1 + "&lccp_cap_val=13667&lccp_capinp_val=13667&submitpnr=Get+Status";
			PNRStatusCrawller check = new PNRStatusCrawller();
		  //StringBuffer data = check.getPNRResponse(reqStr, "http://www.indianrail.gov.in/cgi_bin/inet_pnrstat_cgi.cgi");
			StringBuffer data = check.getPNRResponse(reqStr, "http://www.indianrail.gov.in/cgi_bin/inet_pnstat_cgi_10521.cgi");
				if(data != null) {
				PNRStatus pnr = check.parseHtml2(data);
				if(pnr != null) {
					pnr.setPnr(pnr1);
					System.out.println("Processing PNR rain number=" + pnr.getTrainDetails().getNumber());
					
					PNRResponse res = new PNRResponse();
					res.setStatus(pnr);
					
					// Convert to XML
					JAXBContext jaxbContext = JAXBContext.newInstance(PNRResponse.class);
					Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
					// output pretty printed
					jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
					
					ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
					jaxbMarshaller.marshal(res, bout);
					
					System.out.println(new String(bout.toByteArray()));

				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public StringBuffer getPNRHtml(String uri) throws Exception {
		URL url = new URL(uri);		
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setDoOutput(true);
		connection.setInstanceFollowRedirects(false);
		connection.setRequestMethod("GET");
		connection.setRequestProperty("Content-Type", "text/xml");
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7");
		connection.setRequestProperty("Cache-Control", "max-age=0");
		connection.setRequestProperty("Connection", "keep-alive");
		connection.setRequestProperty("Origin", "http://www.indianrail.gov.in");
		connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		connection.setRequestProperty("Referer", "http://www.indianrail.gov.in/pnr_Enq.html");
		//connection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch");
		connection.setRequestProperty("Accept-Language", "en-US,en;q=0.8");
		connection.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
		//connection.setRequestProperty("Transfer-Encoding", "identity");
		
		// Read the Response
		StringBuffer buff = new StringBuffer();
		
		String encoding = connection.getHeaderField("Transfer-Encoding");
		
		if(encoding != null && encoding.equalsIgnoreCase("chunked")) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line = null;
			while((line = reader.readLine()) != null) {
				buff.append(line + "\n");
			}
			
		} else {
			String ctype = connection.getHeaderField("Content-Length");
			if (ctype != null) {
				int clen = connection.getContentLength();
				if (clen > 0) {
					byte[] res = new byte[clen];
					DataInputStream din = new DataInputStream(connection.getInputStream());
					din.readFully(res);
					
					buff.append(new String(res));
				}
			} else {
				BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
				String line = null;
				while((line = reader.readLine()) != null) {
					buff.append(line + "\n");
				}
			}
		}
		
		// Close the Connection
		connection.disconnect();
		
		return buff;
	}
	
	public StringBuffer getPNRResponse(String payload, String val) throws Exception {
		URL url = new URL(val);		
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setDoOutput(true);
		connection.setInstanceFollowRedirects(false);
		connection.setRequestMethod("POST");
		connection.setRequestProperty("Content-Type", "text/xml");
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7");
		connection.setRequestProperty("Cache-Control", "max-age=0");
		connection.setRequestProperty("Connection", "keep-alive");
		connection.setRequestProperty("Origin", "http://www.indianrail.gov.in");
		connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		connection.setRequestProperty("Referer", "http://www.indianrail.gov.in/pnr_Enq.html");
		//connection.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch");
		connection.setRequestProperty("Accept-Language", "en-US,en;q=0.8");
		connection.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
		//connection.setRequestProperty("Transfer-Encoding", "identity");
		
		OutputStream os = connection.getOutputStream();
		os.write(payload.getBytes());
		os.flush();

		// Read the Response
		StringBuffer buff = new StringBuffer();
		
		String encoding = connection.getHeaderField("Transfer-Encoding");
		
		if(encoding != null && encoding.equalsIgnoreCase("chunked")) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line = null;
			while((line = reader.readLine()) != null) {
				buff.append(line + "\n");
			}
			
		} else {
			String ctype = connection.getHeaderField("Content-Length");
			if (ctype != null) {
				int clen = connection.getContentLength();
				if (clen > 0) {
					byte[] res = new byte[clen];
					DataInputStream din = new DataInputStream(connection.getInputStream());
					din.readFully(res);
					
					buff.append(new String(res));
				}
			} else {
				BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
				String line = null;
				while((line = reader.readLine()) != null) {
					buff.append(line + "\n");
				}
			}
		}
		
		// Close the Connection
		connection.disconnect();
		
		String endStr = buff.toString().substring(buff.toString().length()-8, buff.toString().length()-1);
		
		if(!"</HTML>".equalsIgnoreCase(endStr)) {
			throw new Exception("IncompleteResponseError");
		}
		return buff;
	}
	
	public String parseHtml1(StringBuffer data) throws Exception {
		BufferedReader bin = null;
		if(data != null) {
			bin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data.toString().getBytes())));
		} else {
			return null;
		}

		String line = null;
		String url = null;
		while((line = bin.readLine()) != null) {
			if(line.startsWith("<form") && line.contains("pnr_stat")) {
				String[] tokens = line.split(" ");
				if(tokens != null) {
					for(String kv : tokens) {
						String[] pair = kv.split("=");
						if("action".equalsIgnoreCase(pair[0])) {
							url = pair[1].replaceAll("\"", "");
							break;
						}
					}
					if(url != null) {
						break;
					}
				}
			}
		}
		
		return url;
	}
	
	public PNRStatus parseHtml2(StringBuffer data) throws Exception {
		BufferedReader bin = null;
		if(data != null) {
			bin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data.toString().getBytes())));
		} else {
			return null;
		}

		String line = null;
		PNRStatus pnr = new PNRStatus();
		TrainDetails train = new TrainDetails();
		while((line = bin.readLine()) != null) {
			if(line.equalsIgnoreCase("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"1\" class=\"table_border\">")) {
				boolean keepRun = true;
				while(keepRun) {
					line = bin.readLine();
					if(line.toLowerCase().startsWith("<td") && line.toLowerCase().contains("table_border_both")) {
						train.setNumber(getValue(line));
						train.setName(getValue(bin.readLine()));
						train.setBoardingDate(getValue(bin.readLine()));
						train.setFrom(getValue(bin.readLine()));
						train.setTo(getValue(bin.readLine()));
						train.setReservedUpto(getValue(bin.readLine()));
						train.setBoardingPoint(getValue(bin.readLine()));
						train.setReservedType(getValue(bin.readLine()));
						break;
					}
				}
			} else if(line.equalsIgnoreCase("<TABLE width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"1\" class=\"table_border\" id=\"center_table\" >")) {
				line = bin.readLine();
				while(!line.startsWith("<TD colspan=\"3\" align=\"middle\" valign=\"middle\" class=\"table_border_both\">")) {
					if(line.toLowerCase().startsWith("<td") && line.toLowerCase().contains("table_border_both")) {
						PassengerDetails item = new PassengerDetails();
						item.setName(getValue(line));
						item.setBookingStatus(getValue(bin.readLine()));
						item.setCurrentStatus(getValue(bin.readLine()));
						// Coach Position
						bin.readLine();
						
						pnr.addPassenger(item);
					}
					line = bin.readLine();
				}
				
				// update chart status
				train.setChatStatus(getValue(line));
			}
		}
		
		pnr.setTrainDetails(train);
		
		return pnr;
	}
	

	private static String getValue(String line) {
		if(line == null) {
			return null;
		}
		
		if(!line.contains("<") || !line.contains(">")) {
			return line;
		}
			
		if(line.contains("<") && line.contains(">")) {
			String val = null;
			line = line.replaceAll("<b>", "").replaceAll("</b>", "");
			line = line.replaceAll("<b>", "").replaceAll("</b>", "");
			val = line.substring(line.indexOf(">")+1, line.indexOf("</"));
			val = val.replaceAll("\\*", "");
			return val.trim();
		}
		return null;
	}

}
